#include "Dx.h"
#pragma unmanaged

void Dx::SetResolushion() {
	
}

bool Dx::Init(HWND Hwnd) {
	DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory( &sd, sizeof( sd ) );
    sd.BufferCount = 1;
    sd.BufferDesc.Width = Width;
    sd.BufferDesc.Height = Height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = Hwnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = Windowed;
	D3D_FEATURE_LEVEL FeatureLevels = D3D_FEATURE_LEVEL_11_0;

	
    D3D_FEATURE_LEVEL FeatureLevel;

    if( 0 != D3D11CreateDeviceAndSwapChain( NULL, 
                    D3D_DRIVER_TYPE_HARDWARE,
                    NULL, 
                    0,
                    &FeatureLevels, 
                    1, 
                    D3D11_SDK_VERSION, 
                    &sd, 
                    &g_pSwapChain, 
                    &g_pd3dDevice, 
                    &FeatureLevel,
                    &g_pImmediateContext ))
    {
        return false;
    }
	// Create a render target view
    if(0 != g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer )) return false;
    D3D11_BUFFER_RTV rtv;
	ZeroMemory( &rtv, sizeof( rtv ) );
	rtv.ElementOffset=0;
	rtv.ElementWidth=4;
	D3D11_RENDER_TARGET_VIEW_DESC tv;
	ZeroMemory( &tv, sizeof( tv ) );
	tv.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
	tv.ViewDimension=D3D11_RTV_DIMENSION_BUFFER;
	tv.Buffer=rtv;
    if(0 != g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView )) return false;
 
	// Create depth stencil texture
    D3D11_TEXTURE2D_DESC descDepth;
	ZeroMemory( &descDepth, sizeof( descDepth ) );
    descDepth.Width = Width;
    descDepth.Height = Height;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D32_FLOAT;
    descDepth.SampleDesc.Count = 1;
    descDepth.SampleDesc.Quality = 0;
    descDepth.Usage = D3D11_USAGE_DEFAULT;
    descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;
    if(0 != g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencil )) return false;
   

    // Create the depth stencil view
    D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
	ZeroMemory( &descDSV, sizeof( descDSV ) );
    descDSV.Format = descDepth.Format;
    descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    descDSV.Texture2D.MipSlice = 0;
    if(0 != g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView )) return false;
    
	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(MatrixBuffer);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;
    if(0 != g_pd3dDevice->CreateBuffer( &bd, NULL, &g_pMatrixBuffer )) return false;
	
	return true;
}

void Dx::Deinit() {
	if(g_pMatrixBuffer!=NULL) g_pMatrixBuffer->Release();
	if(g_pRenderTargetView!=NULL) g_pRenderTargetView->Release();
	if(pBackBuffer!=NULL) pBackBuffer->Release();
	if(g_pDepthStencil!=NULL) g_pDepthStencil->Release();
	if(g_pDepthStencilView!=NULL) g_pDepthStencilView->Release();
	if(g_pSwapChain!=NULL) g_pSwapChain->Release();
	if(g_pImmediateContext!=NULL) g_pImmediateContext->Release();
	if(g_pd3dDevice!=NULL) g_pd3dDevice->Release();
}

Dx::Dx() {
	g_pMatrixBuffer=NULL;
	g_pRenderTargetView=NULL;
	pBackBuffer=NULL;
	pBackBuffer=NULL;
	g_pDepthStencil=NULL;
	g_pSwapChain=NULL;
	g_pd3dDevice=NULL;
	g_pImmediateContext=NULL;
	g_pDepthStencilView=NULL;
}

ID3D11DeviceContext* Dx::GetDeviceContext() {
	return g_pImmediateContext;
}

ID3D11DepthStencilView* Dx::GetDepthStencilView() {
	return g_pDepthStencilView;
}

ID3D11RenderTargetView* Dx::GetRenderTargetView() {
	return g_pRenderTargetView;
}

IDXGISwapChain* Dx::GetSwapChain() {
	return g_pSwapChain;
}

void Dx::UpdateMatrixBuffer(MatrixBuffer* buf) {
	if(g_pMatrixBuffer!=NULL && g_pImmediateContext!=NULL) g_pImmediateContext->UpdateSubresource( g_pMatrixBuffer, 0, NULL, buf, 0, 0 );
}

void Dx::Clear()
{
	if(g_pImmediateContext==NULL) return;
	g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView,D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL,0,0);
	float color[4]={0.0f,0.0f,0.0f,0.0f};
	g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView,color);
}

void Dx::Present()
{
	if(g_pSwapChain!=NULL) g_pSwapChain->Present(0,0);
}

ID3D11Device* Dx::GetDevice()
{
	return g_pd3dDevice;
}

#pragma managed
